﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using WebService_Newstore.DAO;
using WebService_Newstore.DTO;
using iTextSharp;
using iTextSharp.text;
using iTextSharp.text.pdf;
using System.IO;


namespace WebService_Newstore.Controller
{
    public class ServicePreparationController
    {
        public static ArticleDTO FindArticlebyId(int idArt)
        {
            ArticleDAO art = new ArticleDAO(idArt);
            ArticleDTO artDTO = new ArticleDTO();
            artDTO.idMySql = idArt;
            artDTO.idOracle = art.idOracle;
            artDTO.idUniteReference = art.idUniteReference;
            artDTO.reference = art.reference;

            return artDTO;
        }

        public static LgBpDTO ChargerLigneBp(int idLgBp)
        {
            LgBpDAO ligneBp = new LgBpDAO(idLgBp);
            LgBpDTO ligneBpDTO = new LgBpDTO();

            //chargement de l'emplacement
            EmplacementDAO emp = EmplacementDAO.getEmplacementByID(ligneBp.idEmplacement);

            //chargement de l'article
            ArticleDAO art = new ArticleDAO(emp.idArticle);

            //affectation des valeurs à l'objet DTO
            ligneBpDTO.id               = ligneBp.id;
            ligneBpDTO.idBp             = ligneBp.idBp;
            ligneBpDTO.idEmplacement    = ligneBp.idEmplacement;
            ligneBpDTO.codeUnite        = ligneBp.codeUnitePrepa;
            ligneBpDTO.numeroLigne      = ligneBp.numeroLigne;
            ligneBpDTO.qteAPrepa        = ligneBp.qteAPrepa;
            ligneBpDTO.qtePreparee      = ligneBp.qtePreparee;
            ligneBpDTO.statut           = ligneBp.statut;
            ligneBpDTO.libEmplacement   = emp.lib;
            ligneBpDTO.refArticle       = art.reference;
            ligneBpDTO.idAnomalie       = ligneBp.idAnomalie;

            return ligneBpDTO;
        }

        //appelé après saisie d'une ligne de préparation
        public static bool SauverLigneBp(LgBpDTO lgBpDto)
        {
            LgBpDAO DAOsave = new LgBpDAO(lgBpDto.id, lgBpDto.idBp, lgBpDto.numeroLigne, lgBpDto.qteAPrepa, lgBpDto.qtePreparee, lgBpDto.statut, lgBpDto.codeUnite, 0,
                lgBpDto.idEmplacement, lgBpDto.idAnomalie, lgBpDto.idLgCmd);
            LgBpDAO.Update(DAOsave);
            return true; // on garde une ouverture si on veut gérer d'éventuelles erreurs
        }

        public static BPDTO ChargerBP(int idBP)
        {
            BpDAO BpDAO = new BpDAO(idBP);
            BPDTO BpDTO = new BPDTO();

            //affectation des valeurs à l'objet DTO
            BpDTO.idBP = BpDAO.numero;
            BpDTO.idCmd = BpDAO.numeroCommande;
            BpDTO.idUser = BpDAO.idUser;
            BpDTO.typeBP = BpDAO.type;
            BpDTO.dateBP = BpDAO.date;
            BpDTO.statutBP = BpDAO.statut;

            return BpDTO;

        }

        //appelé après sauvegarde d'une saisie de ligne de préparation - on modifie le statut et l'id User
        public static bool MajEnteteBp(BPDTO bpDto)
        {
            BpDAO bpDao = new BpDAO(bpDto.idBP, bpDto.dateBP, bpDto.statutBP, bpDto.idCmd, bpDto.typeBP, bpDto.idUser);
            BpDAO.SaveBP(bpDao);
            return true;
        }

        public static EmplacementDTO ChargerEmplacement(int idEmp)
        {
            EmplacementDAO emp = EmplacementDAO.getEmplacementByID(idEmp);
            EmplacementDTO empDTO = new EmplacementDTO();

            empDTO.idEmplacement            = emp.id;
            empDTO.libEmplacement           = emp.lib;
            empDTO.idUnite_Emplacement      = emp.idUnite;
            empDTO.idArticle_Emplacement    = emp.idArticle;
            empDTO.isPicking_Emplacement    = emp.isPicking;
            empDTO.stockQte_Emplacement     = emp.stockQte;
            empDTO.stockAlerte_Emplacement  = emp.stockAlerte;
            empDTO.stockMax_Emplacement     = emp.stockMax;
            return empDTO;
        }

        public static UniteDTO ChargerUnite(int idUn)
        {

            UniteDAO unit = new UniteDAO(idUn);
            UniteDTO unitDTO = new UniteDTO();

            unitDTO.idUnite     = unit.id;
            unitDTO.codeUnite   = unit.code;
            unitDTO.libUnite    = unit.libelle;

            return unitDTO;
        }

        public static List<String> ChargerAnomalies()
        {
            List<AnomalieDAO> listDao = AnomalieDAO.getAnomaliesList();
            List<String> listDto = new List<String>();

            foreach (AnomalieDAO element in listDao)
            {
                //listDto.Add(new AnomalieDTO(element.id, element.libelle));
                listDto.Add(element.id.ToString() + ";" + element.libelle);
            }

            return listDto;
        }

        //nombre de BP prets à être validés en BL pour un User
        public static int CalculerNbBpPourUser(int idUser)
        {
            return BpDAO.CountReadyBp(idUser);
        }

        //test si toutes les lignes d'un BP ont fait l'objet d'une saisie
        public static bool AllBpLinesReady(int bpNo)
        {
            int nb = LgBpDAO.CountNotReadyLines(bpNo);

            if (nb > 0)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        //validation des BP en BL
        public static int GenererBlPourBp(int idBp)
        {
            List<LgBpDAO> ListLg;
            CommandeDAO cd;
            LgCmdDAO lgCmd;
            EmplacementDAO stock;
            int cdNo;
            int nbBl = 0;
            bool flagPrepa = false;

            //lecture de l'entete de BP
            BpDAO bp = new BpDAO(idBp);

            if (bp.numero > 0)
            {
                cdNo = bp.numeroCommande;
                ListLg = LgBpDAO.FindLgByBp(bp.numero);

                //boucle de lecture sur les lignes
                foreach (LgBpDAO lg in ListLg)
                {
                    //MAJ de la ligne de BP --> on la clôture
                    lg.statut = 3;
                    LgBpDAO.Update(lg);
                    
                    //MAJ de la ligne de commande
                    lgCmd = LgCmdDAO.GetLgCmdById(lg.idLgCmd);

                    if (lg.qtePreparee > 0)
                    {
                        flagPrepa = true;
                        lgCmd.QteLivree += lg.qtePreparee;

                        //MAJ de la quantité à l'emplacement
                        stock = EmplacementDAO.getEmplacementByID(lg.idEmplacement);
                        stock.stockQte -= lg.qtePreparee;
                        EmplacementDAO.SaveEmplacementDAO(stock);
                    }

                    if (lgCmd.QteLivree >= lgCmd.QteCommandee)
                    {
                        lgCmd.statut = 3;
                    }
                    else
                    {
                        lgCmd.statut = 1;
                    }
                    LgCmdDAO.SaveLgCmd(lgCmd);

                }

                if (flagPrepa) // --> on imprime le BL
                {
                    ImprimerBL(bp.numero);
                    nbBl++;
                }

                //MAJ du BP --> on le clôture
                bp.statut = 3;
                BpDAO.SaveBP(bp);

                //MAJ de la commande --> on la clôture ou passe en reliquat
                cd = CommandeDAO.GetCmdById(cdNo);
               
                if (LgCmdDAO.CountRemainToDeliver(cdNo) > 0)
                {
                    cd.statutCmd = 1;   
                }
                else
                {
                    cd.statutCmd = 3;
                }
                CommandeDAO.UpdateCmd(cd);
            }

            return nbBl;
        }

        public static PdfPTable InsererCellulesVides(PdfPTable tab, int celDeb, int celFin)
        {
            PdfPCell cellule;
            for (int x = celDeb; x <= celFin; x++)
            {
                cellule = new PdfPCell(new Paragraph(" "));
                cellule.Border = PdfPCell.NO_BORDER;
                tab.AddCell(cellule);
            }
            return tab;
        }

        //insérer cellule
        public static PdfPTable InsererCell(PdfPTable tab, string contenu, int colspan, Font font, bool bordure=false)
        {
            PdfPCell cellule;
            cellule = new PdfPCell(new Paragraph(contenu, font));
            cellule.Colspan = colspan;
            if (bordure == false)
            {
                cellule.Border = PdfPCell.NO_BORDER;
            }
            tab.AddCell(cellule);
            return tab;
        }

        // insertion de l'entete du BL
        public static PdfPTable InsererEnteteBL(PdfPTable tableau, int bpNo, int noPage)
        {
            BpDAO bp = new BpDAO(bpNo);
            CommandeDAO cmd = CommandeDAO.GetCmdById(bp.numeroCommande);
            HyperDAO hyper = new HyperDAO(cmd.idHyper);
            PdfPCell cellule;
            Image img = Image.GetInstance("C:/Users/Yohann/workspace/newstorepfr/WebService_Newstore/WebService_Newstore/Content/Images/newstore_logo.png");
            img.ScaleAbsolute(120, 40);
            BaseFont bfont;
            Font font;
            cellule = new PdfPCell(img);
            cellule.Colspan = 5;
            cellule.Border = PdfPCell.NO_BORDER;
            tableau.AddCell(cellule);

            bfont = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1252, false);
            font = new Font(bfont, 16, Font.BOLD, BaseColor.BLACK);

            InsererCell(tableau, "BON DE LIVRAISON N°" + bpNo.ToString(), 5, font);

            bfont = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1252, false);
            font = new Font(bfont, 12, Font.ITALIC, BaseColor.BLACK);

            InsererCell(tableau, "NEWSTORE PLATEFORME", 5, font);
            InsererCell(tableau, hyper.nom.ToUpper(), 5, font);
            InsererCell(tableau, "11 RUE TEST", 5, font);
            InsererCell(tableau, hyper.rue.ToUpper(), 5, font);
            InsererCell(tableau, "ZAC", 5, font);
            InsererCell(tableau, hyper.cplAdresse.ToUpper(), 5, font);
            InsererCell(tableau, "29000 BREST", 5, font);
            InsererCell(tableau, hyper.cPostal.ToUpper() + " " + hyper.ville.ToUpper(), 5, font);
            InsererCell(tableau, "FRANCE", 5, font);
            InsererCell(tableau, "FRANCE", 5, font);
            InsererCellulesVides(tableau, 1, 8);
            InsererCell(tableau, "PAGE " + noPage.ToString(), 2, font);

            //entetes des colonnes
            bfont = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1252, false);
            font = new Font(bfont, 14, Font.BOLD, BaseColor.BLACK);

            InsererCell(tableau, "REFERENCE", 6, font, true);
            InsererCell(tableau, "QTE LIVREE", 2, font, true);
            InsererCell(tableau, "UNITE", 2, font, true);

            return tableau;
        }

        public static PdfPTable InsererPiedBL(PdfPTable tableau, int bpNo)
        {
            BaseFont bfont;
            Font font;
            BpDAO bp = new BpDAO(bpNo);
            UserDAO user = new UserDAO(bp.idUser);

            bfont = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1252, false);

            font = new Font(bfont, 16, Font.BOLD, BaseColor.BLACK);
            InsererCell(tableau, "Préparateur", 3, font);

            font = new Font(bfont, 16, Font.NORMAL, BaseColor.BLACK);
            InsererCell(tableau, user.nomUserDAO + " " + user.preUserDAO, 7, font);

            font = new Font(bfont, 10, Font.BOLD, BaseColor.BLACK);
            InsererCell(tableau, "Intracom: 878151815", 4, font);
            InsererCell(tableau, "Naf: 5489", 3, font);
            InsererCell(tableau, "Siret: 6 98794555", 3, font);


            return tableau;
        }

        //imprimer le BL (n° de BP en paramètre)
        public static void ImprimerBL(int bpNo)
        {
            //Génération du fichier pdf
            Document pdfBP = new Document();
            BaseFont bfont;
            Font font;
            List<LgBpDAO> listLg = LgBpDAO.FindLgByBp(bpNo);
            int nbLg = 0;
            int noPage = 1;

            string path = @"C:\Users\Yohann\Desktop\";
            try
            {
                PdfWriter.GetInstance(pdfBP, new FileStream(path + "BL" + bpNo.ToString() + ".pdf", FileMode.Create, FileAccess.ReadWrite));
                pdfBP.Open();
                
                //Ajout Tableau --> paramètre: nombre de colonnes max que comporteront les lignes
                PdfPTable tableau = new PdfPTable(10) ;
                tableau.WidthPercentage = 100;

                //Lignes (on doit atteindre le nombre de cellules pour passer à la ligne suivante) --> 36 lignes par page max
                foreach (LgBpDAO lgBP in listLg)
                //for(int x = 1; x<=90; x++)
                {
                    if (lgBP.qtePreparee > 0)
                    {
                        if (nbLg == 36)
                        {
                            InsererPiedBL(tableau, bpNo);
                            nbLg = 0;
                            noPage++;
                        }

                        if (nbLg == 0)
                        {
                            InsererEnteteBL(tableau, bpNo, noPage);
                        }

                        bfont = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1252, false);
                        font = new Font(bfont, 12, Font.NORMAL, BaseColor.BLACK);

                        LgCmdDAO lgCmd = LgCmdDAO.GetLgCmdById(lgBP.idLgCmd);
                        ArticleDAO art = new ArticleDAO(lgCmd.idArticle);
                        InsererCell(tableau, art.reference, 6, font, true);
                        InsererCell(tableau, lgBP.qtePreparee.ToString(), 2, font, true);
                        InsererCell(tableau, lgBP.codeUnitePrepa, 2, font, true);

                        nbLg++;
                    }
                }

                //pour que le pied de page soit positionné au bon endroit
                for (int x = nbLg; x < 36; x++)
                {
                    InsererCellulesVides(tableau, 1, 10);
                }

                InsererPiedBL(tableau, bpNo);

                //
                pdfBP.Add(tableau);
                pdfBP.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.InnerException.ToString() + " - Erreur Génération PDF");
            }
        }

        public static int Test(int bpNo)
        {
            ImprimerBL(bpNo);

            return 0;
        }
    }
}
